package com.cnc.fd.util;

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;

import org.apache.commons.lang.StringUtils;
 
public class UtilEncrypt {
    public static String encrypt(String strSrc, String encName) {
        MessageDigest md = null;
        String strDes = null;

        byte[] bt = strSrc.getBytes();
        try {
            if (encName == null || encName.equals("")) {
                encName = "MD5";
            }
            md = MessageDigest.getInstance(encName);
            md.update(bt);
            strDes = bytes2Hex(md.digest()); // to HexString
        } catch (NoSuchAlgorithmException e) {
            System.err.println("Invalid algorithm.");
            return null;
        }

        return strDes;
    }

    public static byte[] hex2Bytes(byte[] bts) {

        if ((bts.length % 2) != 0)

            throw new IllegalArgumentException("Length isn't even!");

        byte[] bts2 = new byte[bts.length / 2];

        for (int n = 0, len = bts.length; n < len; n += 2) {

            String item = new String(bts, n, 2);

            bts2[n / 2] = (byte) Integer.parseInt(item, 16);

        }

        return bts2;
    }

    public static String bytes2Hex(byte[] bts) {
        String result = "";
        String tmp = null;

        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                result += "0";
            }
            result += tmp;
        }

        return result;
    }

    /**
     * DES加密
     * 
     * @param src
     *            数据源
     * @param key
     *            密钥，长度必须是8的倍数
     * @return 返回加密后的数据
     * @throws Exception
     */
    public static String desEncrypt(String strSrc, String key, String encName)
            throws Exception {
        // DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();

        // 从原始密匙数据创建一个DESKeySpec对象
        KeySpec ks = null;

        if (EncryptConstants.ENCODE_DES.equals(encName)) {
            ks = new DESKeySpec(key.getBytes());
        } else if (EncryptConstants.ENCODE_DESEDE.equals(encName)) {
            ks = new DESedeKeySpec(key.getBytes());
        } else {
            throw new NullPointerException("The Name Of Encrypt Code Is Null!");
        }

        // 创建一个密匙工厂，然后把KeySpec对象转换成一个SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encName);
        SecretKey securekey = keyFactory.generateSecret(ks);

        // 执行加密操作
        return operateEncryptKey(strSrc, securekey, "DES", Cipher.ENCRYPT_MODE,
                sr);
    }

    /**
     * DES解密
     * 
     * @param src
     *            数据源
     * @param key
     *            密钥，长度必须是8的倍数
     * @return 返回解密后的原始数据
     * @throws Exception
     * @throws Exception
     */
    public static String desDecrypt(String strSrc, String key, String encName)
            throws Exception {
        // DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();

        // 从原始密匙数据创建一个KeySpec对象
        KeySpec ks = null;

        if (EncryptConstants.ENCODE_DES.equals(encName)) {
            ks = new DESKeySpec(key.getBytes());
        } else if (EncryptConstants.ENCODE_DESEDE.equals(encName)) {
            ks = new DESedeKeySpec(key.getBytes());
        } else {
            throw new NullPointerException("The Name Of Encrypt Code Is Null!");
        }

        // 创建一个密匙工厂，然后把KeySpec对象转换成一个SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encName);
        SecretKey securekey = keyFactory.generateSecret(ks);

        // 执行解密操作
        return operateEncryptKey(strSrc, securekey, encName,
                Cipher.DECRYPT_MODE, sr);
    }

    /**
     * 生成（对称）密钥
     * 
     * @param encName
     * @param digit
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Key generateSymmetricalKey(String encName, int keysize)
            throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance(encName);

        keyGen.init(keysize);

        return keyGen.generateKey();
    }

    /**
     * 生成公钥和私钥对
     * 
     * @param encName
     * @param digit
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static KeyPair generateUnSymmetricalKey(String encName, int keysize,
            SecureRandom random) throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(encName);

        if (random == null) {
            keyGen.initialize(keysize);
        } else {
            keyGen.initialize(keysize, random);
        }

        return keyGen.generateKeyPair();

    }

    /**
     * 加密私有密钥
     * 
     * @param src
     * @param encName
     * @param digit
     * @param encMethod
     * @param encPadding
     * @return
     * @throws Exception
     */
    private static byte[] operateEncryptKey(String strSrc, Key key,
            String encName, String encMethod, String encPadding, int opmode,
            SecureRandom random) throws Exception {
        byte[] src = strSrc.getBytes();

        String transformation = encName;

        if (StringUtils.isNotEmpty(encMethod)) {
            transformation += "//" + encMethod;
        }

        if (StringUtils.isNotEmpty(encPadding)) {
            transformation += "//" + encPadding;
        }

        // 获得一个私钥加密类Cipher
        Cipher cipher = Cipher.getInstance(transformation);

        // 使用私钥进行加密或解密
        if (random == null) {
            cipher.init(opmode, key);
        } else {
            cipher.init(opmode, key, random);
        }

        return cipher.doFinal(src);
    }

    private static String operateEncryptKey(String strSrc, Key key,
            String encName, String encMethod, String encPadding, int opmode)
            throws Exception {
        return new String(operateEncryptKey(strSrc, key, encName, encMethod,
                encPadding, opmode, null));
    }

    private static String operateEncryptKey(String strSrc, Key key,
            String encName, int opmode, SecureRandom random) throws Exception {
        return new String(operateEncryptKey(strSrc, key, encName, null, null,
                opmode, random));
    }

    private static String operateEncryptKey(String strSrc, Key key,
            String encName, int opmode) throws Exception {
        return new String(operateEncryptKey(strSrc, key, encName, null, null,
                opmode, null));
    }
   
}
